package com.hm.base.auto.helper;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.hm.base.auto.SystemEnvConfigProperties;
import com.hm.base.auto.su.R.Restful;
import com.hm.base.service.AuthorizationService;
import com.hm.base.service.ReqLogService;
import com.hm.base.vo.LoginSubscriberVo;
import com.hm.base.vo.ReqLogVo;
import com.hm.common.annotation.WebClientRequestIntercept;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.util.CommonUtil;
import com.hm.common.util.EncryptUtil.AES;
import com.hm.common.util.RemoteClientUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shishun.wang
 * @date 上午10:21:53 2017年6月5日
 * @version 1.0
 * @describe
 */
@Slf4j
@Aspect
@Component
public class ApiAspectHandler {

	@Autowired
	private SystemEnvConfigProperties systemEnvConfigProperties;

	@Autowired
	private AuthorizationService authorizationService;

	@Autowired
	private ReqLogService reqLogService;

	@Around("execution(* com.hm.base.api.**Api.*(..))")
	public Object process(ProceedingJoinPoint point) throws Throwable {

		Method method = ((MethodSignature) point.getSignature()).getMethod();
		WebClientRequestIntercept intercept = method.getAnnotation(WebClientRequestIntercept.class);
		if (null != intercept && !intercept.auth()) {
			return point.proceed();
		}

		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();

		String token = request.getHeader(Restful.REMOTE_CLIENT_AUTHORIZATION);
		if (CommonUtil.isEmpty(token)) {
			if (systemEnvConfigProperties.isDevModel()) {
				request.setAttribute(Restful.REMOTE_CLIENT_AUTHORIZATION_DEV,
						AES.encrypt(systemEnvConfigProperties.getDevModelUser() + ":" + System.currentTimeMillis()));
				return point.proceed();
			}
			log.error("token丢失,会话超时重新登陆");
			throw ServiceException.warning(ErrorCode.SESSION_TIME_OUT);
		}

		this.checkRemoteRequestToken(token);
		if (systemEnvConfigProperties.isOpenReqLogRecord()) {
			this.recordReqLog(RemoteClientUtil.getHost(request), request.getRequestURI());
		}
		return point.proceed();
	}

	private void checkRemoteRequestToken(String token) {
		Long subscriberId = 0l;
		Long loginTime = 0l;
		try {// 验证token 是否合法
			String[] decrypt = AES.decrypt(token).split(":");
			subscriberId = Long.valueOf(decrypt[0]);
			loginTime = Long.valueOf(decrypt[1]);
		} catch (Exception e) {
			log.error("token解析失败", e);
			throw ServiceException.warning(ErrorCode.NO_DATA_ACCESS);
		}

		LoginSubscriberVo loginToken = authorizationService.loadLoginToken(subscriberId);
		if (CommonUtil.isEmpty(loginToken) || (loginTime != loginToken.getCurrentLoginTime())) {
			log.error("token丢失,会话超时重新登陆");
			throw ServiceException.warning(ErrorCode.SESSION_TIME_OUT);
		}
	}

	@Async
	private void recordReqLog(String host, String reqUri) {
		try {
			ReqLogVo reqLogVo = new ReqLogVo();
			{
				reqLogVo.setCreateUser(HmSessionFactory.currentUserId());
				reqLogVo.setReqName(host);
				reqLogVo.setReqSource("HM-BASE-REQ-LOG");
				reqLogVo.setReqUri(reqUri);
				reqLogVo.setNote("基础服务API调用日志记录");
			}
			reqLogService.addReqLog(reqLogVo);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}

}
